/**************************************************************************/
/*  Copyright (C) School of Software Engineering of USTC, 2013             
/*                                                                        
/*  FILE NAME: ProbC.c                                                  
/*  PRINCIPAL AUTHOR: SA12226340(Song Zeyu)                                                                                                          
/*  LANGUAGE: C++/C                                                          
/*  TARGET ENVIRONMENT: Linux                                             
/*  DATE OF FIRST RELEASE: 2013-06-10                                    
/*  DESCRIPTION:Realization mail spam filtering ,Bayesian spam filtering              
/**************************************************************************/

#include "ProbC.h"
#include "common.h"

#define SPAMSIZE 50         /*垃圾邮件集的数量*/
#define PAMSIZE 50           /*正常邮件集的数量*/
#define MAXWORDS 15           /*邮件中类别概率最大的单词个数*/


/*
*查找单词在邮件库（垃圾库，合法库）中出现的次数
*/
int FindWordNum(char *word,map<string,int> maillib)/*查找单词在邮件库（垃圾库，合法库）中出现的次数*/
{	
	int wordnumslib;
	wordnumslib = FindWordNumsLib(word,maillib);
	return wordnumslib;
}

/*
*求某个关键词出现邮件为垃圾邮件的概率
*/
double SinWordProb(char *word,map<string,int>spam_map,map<string,int>pam_map)
{
	/*p(s|w) = p(w|s)/(p(w|s) + p(w|h)) */
	int wordspamnum;                  /*单词在垃圾库中出现的次数*/
	int wordpamnum;                       /*单词在合法库中出现的次数*/
	double wordspamlibprob = 0.0;   /*wordspamprob为单个词出现在垃圾邮件中的先验的概率*/
	double wordpamlibprob =0.0;     /*wordpamprob为单个词出现在垃圾邮件中的先验的概率*/
	double mailspamprob;
	wordspamnum = FindWordNum(word,spam_map);
	wordpamnum = FindWordNum(word,pam_map);
	printf("wordspamnum = %d,wordpamnum = %d\n",wordspamnum,wordpamnum);
	
	if((wordpamnum !=0) && (wordspamnum == 0))   /*如果某个词只出现在合法库中，没有出现在垃圾库中，则假定在垃圾库中的概率为0.1*/
	{
		wordspamlibprob = 0.1;
		wordpamlibprob = double(wordpamnum)/PAMSIZE;
		mailspamprob = wordspamlibprob/(wordspamlibprob + wordpamlibprob);
		return mailspamprob;
	}
	else if((wordpamnum ==0) && (wordspamnum != 0))  /*如果某个词只出现在垃圾库中，没有出现在合法库中，则假定在合法库中的概率为0.1*/
	{
		wordpamlibprob = 0.1;
		wordspamlibprob = double(wordspamnum)/SPAMSIZE;
		mailspamprob = wordspamlibprob/(wordspamlibprob + wordpamlibprob);
		return mailspamprob;
	} 
	else if((wordpamnum !=0) && (wordspamnum != 0))   /*如果某个词既出现在垃圾库中，也出现在合法库中*/
	{
		wordpamlibprob = double(wordpamnum)/PAMSIZE;
		wordspamlibprob = double(wordspamnum)/SPAMSIZE;
		mailspamprob = wordspamlibprob/(wordspamlibprob + wordpamlibprob);
		return mailspamprob;
	}
	else if((wordpamnum==0)&&(wordspamnum==0))  /*如果某个词既没有出现在垃圾库中，也没有出现在合法库中，则该邮件因为该词为垃圾邮件的概率为0*/
    {
    	mailspamprob = 0.4;     /*这个词第一次出现，则是垃圾邮件的概率为0.4*/
    	return mailspamprob;
    }
 
}

/*
*求一封邮件中邮件类别概率最高的关键词的数组
*/
double *WordsMaxProb(map<string,int> mailmap,map<string,int> spam_map,map<string,int> pam_map,int &wordslen)
{
	int mailwordsize = 0;
	double *wordsprob = NULL;  /*存放邮件中所有词的概率*/
	int index = 0;
	char word[30] = {0};      /*存放一个单词*/
	double *result = NULL;   /*存放p(s|w)最高的15个单词的频率*/
	
	map <string,int> ::iterator iter;
	
	mailwordsize = MapWordSizeStr(mailmap);
	printf("mailwordsize = %d\n",mailwordsize);
	wordsprob = (double*)calloc(mailwordsize,sizeof(double));/*动态创建数组*/
	result = (double*)calloc(MAXWORDS,sizeof(double));/*动态创建数组*/
	for(iter = mailmap.begin();iter!=mailmap.end();iter++)
	{	
		strcpy(word,iter->first.c_str());/*将string转换成char[]*/
		wordsprob[index++] = SinWordProb(word,spam_map,pam_map);	
	}
	sort(wordsprob,wordsprob + mailwordsize);/*排序，排序结果为从小到大*/
	
	#if 0
	for(index = mailwordsize-1;index >=0;index--)
	{
		printf("wordsprob[%d]:%f\n",index,wordsprob[index]);
	}
	#endif
	if(MAXWORDS <=mailwordsize)
	{
		for(index = 0;index <MAXWORDS;index++)
		{
			result[index] = wordsprob[mailwordsize--];
		}
		wordslen = MAXWORDS;
	}
	else
	{
		wordslen = mailwordsize;
		result = wordsprob;
	}
	return result;
	//free(wordsprob);
}

/*选出单个词出现邮件为垃圾概率最高的15个词，计算联合概率，公式如下*/
double WordsJointProb(double wordprob[],int wordnums)
{
	//(p1 * p2 * ...p15)/(p1 * p2 * ...p15 +(1-p1) *(1- p2) * ...(1-p15))
	double mailprob;
	double tmpprob1 = wordprob[0];
	double tmpprob2 = 1-wordprob[0];
	int index;
	
	for(index=0;index<wordnums;index++)
	{
		printf("wordprob[%d] is %f\n",index,wordprob[index]);
	}
	
	for(index = 1;index < wordnums;index++)
	{
		tmpprob1 *= wordprob[index]; 
		tmpprob2 *=(1-wordprob[index]);
	}
	mailprob = tmpprob1 / (tmpprob1 + tmpprob2);
	printf("mailprob is %f,tmpprob1 is %f, tmpprob2 is %f\n",mailprob,tmpprob1,tmpprob2);
	return mailprob;
}






